#include "FigureObject.h"
namespace SLG
{
	FigureObject::FigureObject(World* w)
	{
		m_world=w;
		m_mManager=new ModelManager;
		m_fManager=new FigureManager;
		m_tManager=new TextureManager;
		m_aManager=new AnimManager(m_mManager,m_fManager);
	}

	FigureObject::~FigureObject(void)
	{
		delete m_mManager;
		delete m_fManager;
		delete m_aManager;
		delete m_tManager;
	}

	bool FigureObject::AddFigure(int32 id, int32 mid, const char* name, int32 x, int32 y, FACE f)
	{
		//D3DXVECTOR3 pos=m_world->GetCellPos(x,y);
		if(!m_world->CheckCell(x,y))
		{
			return false;
		}
		int32 _mid=m_mManager->HasObj(mid);
		if(m_fManager->AddObj(id,_mid,name,x,y,f))
		{
			if(m_world->AddFigureInCell(m_fManager->m_cur-1,x,y))
				return true;
		}
		return false; 
	}

	int32 FigureObject::AddTexture(char* name, LPDIRECT3DTEXTURE9 tex)
	{
		return m_tManager->AddObj(name,tex);
	}

	bool FigureObject::AddModel(int32 mid, int32 tid, char* name, Model* model)
	{
		return m_mManager->AddObj(mid,tid,name,model);
	}

	bool FigureObject::LoadAnim()
	{
		for(vector<FIGURE>::iterator iter=m_fManager->m_data.begin();iter<m_fManager->m_data.end();iter++)
		{
			Model* m=m_mManager->GetModel(iter->mid);
			if(m==NULL)
				return false;
			int32 anim=0;
			for(uint32 i=0;i<m->header->nAnimations;i++)
			{
				if(m->anims[i].animID==0)
				{
					anim=i;
					break;
				}

			}
			if(!m_aManager->AddObj(iter->id,iter->name,anim))
				return false;
			if(ChangeAABB(iter->id,m->anims[anim].boundSphere))
					return true;
		}
		return true;
	}

	HRESULT FigureObject::CreateVetices()
	{
		for(vector<ANIMATION>::iterator iter=m_aManager->m_data.begin();
			iter<m_aManager->m_data.end();
			iter++)
		{
			if(iter->vertices==NULL)
				continue;
			Model* m=m_mManager->GetModel(m_fManager->GetMid(iter->fid));
			for(vector<Map>::iterator iter2=m->RenderMap.begin();iter2<m->RenderMap.end();iter2++)
			{
				if(iter->vertices==NULL)
					continue;
				if(!InitMap(&*iter2,m,iter->anim))
				{
					continue;
				}
				LPDIRECT3DVERTEXBUFFER9 vb; // Buffer to hold vertices
				if( FAILED( g_pd3dDevice->CreateVertexBuffer( (iter2->indexCount) * sizeof( CUSTOMVERTEX ),
					0, D3DFVF_CUSTOMVERTEX,
					D3DPOOL_DEFAULT, &vb, NULL ) ) )
				{
					return E_FAIL;
				}

				CUSTOMVERTEX* pVertices;

				if( FAILED( vb->Lock( 0, 0, ( void** )&pVertices, 0 ) ) )
					return E_FAIL;
				for( size_t k = 0,b=iter2->indexStart; k < iter2->indexCount; k++,b++ )
				{
					uint16 a = m->indices[b];
					pVertices[k].position = iter->vertices[a];
					pVertices[k].tu=m->vertices[a].texcoords.x;
					pVertices[k].tv=m->vertices[a].texcoords.y;
				}
				vb->Unlock();
				m_fManager->AddVB(iter->fid,vb,iter2->indexCount/3);
			}

		}

		return S_OK;
	}

	
	bool FigureObject::InitMap(Map* map,Model* model,int32 anim)
	{
		D3DXVECTOR4 ocol = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);
		D3DXVECTOR4 ecol = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);
		ModelColor* colors=model->colors;

		//if (m->trans == 1.0f)
		//	return false;

		// emissive colors
		if (map->color!=-1 && colors && colors[map->color].color.uses(0)) 
		{
			D3DXVECTOR3 c;
			c = colors[map->color].color.getValue(0,model->animtime);
			if (colors[map->color].opacity.uses(anim)) 
			{
				ocol.w = colors[map->color].opacity.getValue(anim,model->animtime);
			}


			if (map->unlit) 
			{
				ocol.x = c.x; ocol.y = c.y; ocol.z = c.z;
			} else 
			{
				ocol.x = ocol.y = ocol.z = 0;
			}

			ecol = D3DXVECTOR4(c, ocol.w);
		}

		// opacity
		if (map->opacity!=-1) 
		{

			if (model->transparency && model->transparency[map->opacity].trans.uses(0))
				ocol.w *= model->transparency[map->opacity].trans.getValue(0, model->animtime);


			// exit and return false before affecting the opengl render state
			if (!((ocol.w > 0) && (map->color==-1 || ecol.w > 0)))
				return false;
			else
				return true;
		}
		return true;
	}

	bool FigureObject::ChangeAABB(int32 fid,Sphere s)
	{
		FIGURE* tmp=&m_fManager->m_data[fid];
		if(m_fManager->m_data.size()<=fid)
			return false;
		if(tmp->aabb!=NULL)
			delete tmp->aabb;
		tmp->aabb= new AABB(s.min,s.max,s.radius);
		return false;
	}

	
	void FigureObject::RenderData()
	{

		g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
		// Begin the scene
		// Render the vertex buffer contents
		D3DXMATRIXA16 matWorld;
		int i=0;
		for(vector<FIGURE>::iterator iter=m_fManager->m_data.begin();iter<m_fManager->m_data.end();iter++,i++)
		{
			D3DXMatrixIdentity( &matWorld );
			D3DXVECTOR3 pos=m_world->GetCellPos(iter->cell_x,iter->cell_y);
			D3DXMatrixTransformation(&matWorld,NULL,NULL,NULL,NULL,NULL,&pos);
			g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
			OBJ* o=m_mManager->GetObj(iter->mid);
			TEXTURE* t=m_tManager->GetObj(o->tid);

			g_pd3dDevice->SetTexture( 0,t->tex);

			g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
			g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
			g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );

			g_pd3dDevice->SetRenderState(D3DRS_ALPHAREF,(DWORD)0x000000A5);
			g_pd3dDevice->SetRenderState(D3DRS_ALPHAFUNC,D3DCMP_GREATEREQUAL);
			for(int32 i=0;i<iter->nVB;i++)
			{
				g_pd3dDevice->SetStreamSource( 0, iter->VB[i].pVB, 0, sizeof( CUSTOMVERTEX ) );
				g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
				g_pd3dDevice->DrawPrimitive(  D3DPT_TRIANGLELIST , 0, iter->VB[i].count);
			}

		}
		// End the scene
		g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
	}

	void FigureObject::RenderFigure(DWORD t)
	{
		m_aManager->CalcAnim(t);
		CreateVetices();
		RenderData();
		m_fManager->ClearVB();
	}
}